﻿using Newtonsoft.Json;
using Sumc.Client.ModernUI.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;

namespace Sumc.Client.ModernUI.Services
{
    public abstract class BaseRepository
    {
        private readonly static HashSet<char> invalidFilenameCharacters = new HashSet<char>(Path.GetInvalidFileNameChars());
        protected TimeSpan expireTime = new TimeSpan(0, 0, 0);
        protected readonly TimeSpan zeroTimeSpan = new TimeSpan(0, 0, 0);

        protected async Task<T> Get<T>(string url)
        {
            string responseString = null;
            if (this.expireTime > zeroTimeSpan)
            {
                var key = await this.GetKey(url);
                try
                {
                    var file = await ApplicationData.Current.TemporaryFolder.GetFileAsync(key);
                    if (file.DateCreated.Add(this.expireTime) > DateTime.Now)
                    {
                        var read = await FileIO.ReadTextAsync(file);
                        var readAsObject = await JsonConvert.DeserializeObjectAsync<T>(read);
                        return readAsObject;
                    }
                }
                catch (Exception) { }

                responseString = await this.Get(url);
                var cache = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);
                await FileIO.WriteTextAsync(cache, responseString);
            }
            else
            {
                responseString = await this.Get(url);
            }

            var responseAsObject = await JsonConvert.DeserializeObjectAsync<T>(responseString);
            return responseAsObject;
        }

        private async Task<string> Get(string url)
        {
            using (var client = new HttpClient())
            {
                var response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();

                var responseString = await response.Content.ReadAsStringAsync();
                return responseString;
            }
        }

        protected async Task<T> Post<T>(string url, IEnumerable<KeyValuePair<string, string>> data)
        {
            var content = new FormUrlEncodedContent(data);
            using (var client = new HttpClient())
            {
                var response = await client.PostAsync(url, content);
                response.EnsureSuccessStatusCode();

                var reseponseAsObject = await response.Content.ReadAsAsync<T>();
                return reseponseAsObject;
            }
        }

        private Task<string> GetKey(string url)
        {
            return Task.Run<string>(() =>
            {
                var urlLength = url.Length;
                var builder = new StringBuilder(urlLength);
                for (int i = 0; i < urlLength; i++)
                {
                    var character = url[i];
                    if (!invalidFilenameCharacters.Contains(character))
                    {
                        builder.Append(character);
                    }
                }

                return builder.ToString();
            });
        }
    }
}
